package com.douqu.game.auth.service;


import com.alibaba.fastjson.JSONObject;
import com.bean.core.util.HttpJsonUtils;
import com.bean.core.util.MD5Utils;
import com.bean.core.util.TimeUtils;
import com.bean.core.util.Utils;
import com.douqu.game.auth.database.mapper.*;
import com.douqu.game.auth.database.model.*;
import com.douqu.game.auth.server.SpringContext;
import com.douqu.game.auth.web.request.QueryTotalRechargeReqDto;
import com.douqu.game.auth.web.request.UseCodeReqDto;
import com.douqu.game.core.database.model.MergeModel;
import com.douqu.game.core.e.E_CdkCodeType;
import com.douqu.game.core.e.E_QueryRechargeCountType;
import com.douqu.game.core.e.ReturnMessage;
import com.douqu.game.core.entity.common.TwoTuple;
import com.douqu.game.core.util.CoreUtils;
import com.douqu.game.core.util.LogUtils;
import com.douqu.game.core.web.response.*;
import com.douqu.game.core.util.StringUtils;
import io.netty.util.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.*;

/**
 * Author : wangzhenfei
 * 2017-07-06 15:55
 */
@Service
public class ServerServiceImpl implements ServerService {
    @Autowired
    ServerMapper serverMapper;

    @Autowired
    ServerTaskMapper serverTaskMapper;

    @Autowired
    CdkCodeMapper cdkCodeMapper;

    @Autowired
    CdkUseRecordMapper cdkUseRecordMapper;

    @Autowired
    CdkDetailMapper cdkDetailMapper;

    @Autowired
    OrderRecordMapper orderRecordMapper;

    @Autowired
    RoleRecordMapper roleRecordMapper;

    @Autowired
    ServerMergeMapper serverMergeMapper;

    @Override
    public BaseResponseDto changeStatus(String password, Integer serverId, Integer status, String version)
    {
        LogUtils.info("changeStatus 参数 serverId：" + serverId + ", password: " + password + "， status: " + status + " version:" + version);
        if(serverId == null || serverId.intValue() == 0 || status == null || status.intValue() == 0){
            return new ErrorResponseDto(ReturnMessage.EMPTY_PARAM);
        }

        ServerModel serverModel = serverMapper.selectByPrimaryKey(serverId);
        if(serverModel == null){
            LogUtils.error("没有对应的 serverId：" + serverId);
            return new ErrorResponseDto(ReturnMessage.SERVER_ID_ERROR);
        }

        //验证密码
        String checkString = serverModel.getId() + "" + TimeUtils.getCurrentTime(TimeUtils.YYYYMMDD);
        LogUtils.debug("checkString -> " + checkString);
        String md5Code = MD5Utils.encodeUppercase(checkString);
        if(!md5Code.equals(password)){
            LogUtils.error("changeStatus 密码错误, 正确密码：" + md5Code);
            return new ErrorResponseDto(ReturnMessage.PASSWORD_ERROR);
        }

        serverMapper.changeStatus(serverId, status);
        return new SuccessResponseDto();
    }

//   @Override
//        @Transactional(rollbackFor = Exception.class)
//    public BaseResponseDto addCdkCode(AddCdkCodeReqDto request) {
//        LogUtils.info("addCdkCode 参数：" + request.toString());
//        if(!request.checkParam()){
//            return new ErrorResponseDto(ReturnMessage.PARAM_ERROR);
//        }
//        List<CdkCodeModel> models = new ArrayList<>();
//        String lastCode = null;
//
//        if(E_CdkCodeType.SINGLE_REPEAT_USE.getCode() == request.getType()){
//            CdkCodeModel model = cdkCodeMapper.getMaxCodeByType(request.getType(), request.getGroup());
//            lastCode = model == null ? null : model.getCode();
//        }else {
//            int group;
//            if(request.getGroup() == 0){ //使用新的组
//                Integer maxGroupNum = cdkCodeMapper.getMaxGroupNum(request.getChannel(), request.getProject());
//                maxGroupNum = maxGroupNum == null ? 0 : maxGroupNum.intValue();
//                if(maxGroupNum == 0){ //还没有任何组
//                    group = 1;
//                }else {
//                    //获取最小可用组
//                    Integer minGroup = cdkCodeMapper.getMinInvalidGroup(request.getChannel(), request.getProject());
//                    minGroup = minGroup == null ? 0 : minGroup;
//                    if(minGroup == 0){ // 没有最小可用组
//                        if(maxGroupNum == 9){ // 已经达到最大，不能添加了
//                            return new ErrorResponseDto(ReturnMessage.CDK_GROUP_FULL);
//                        }else{
//                            group = maxGroupNum + 1;
//                        }
//                    }else {
//                        group = minGroup;
//                    }
//                }
//                request.setGroup(group);
//
//            }else { //在原来的组上进行扩充
//                CdkCodeModel modle = cdkCodeMapper.getMaxCodeByType(request.getType(), request.getGroup());
//                if(modle == null){
//                    return new ErrorResponseDto(ReturnMessage.CDK_GROUP_NOT_FIND);
//                }
//                lastCode = modle.getCode();
//            }
//        }
//
//        List<String> cdks = Utils.cdkCreate(lastCode, request.getCount());
//        for(String cdk : cdks){
//            models.add(new CdkCodeModel(request, cdk));
//        }
//        cdkCodeMapper.insertBatch(models);
//        return new BaseResponseDto<CommonResponseListDto>(ReturnMessage.SUCCESS, new CommonResponseListDto<CdkCodeModel>(models));
//    }

    @Override
    public BaseResponseDto useCdkCode(UseCodeReqDto request) {
        if(request == null){
            return new ErrorResponseDto(ReturnMessage.PARAM_ERROR);
        }

        if(StringUtils.isNullOrEmpty(request.getCdk()) ||
                StringUtils.isNullOrEmpty(request.getObjectIndex()) ||
                StringUtils.isNullOrEmpty(request.getNickName())){
            return new ErrorResponseDto(ReturnMessage.PARAM_ERROR);
        }
        LogUtils.info("收到使用CDK的请求->", request);
        ServerModel serverModel = serverMapper.selectByPrimaryKey(request.getServerId());
        if(serverModel == null){
            LogUtils.debug("没有对应的 serverId：" + request.getServerId());
            return new ErrorResponseDto(ReturnMessage.SERVER_ID_ERROR);
        }
        //先把cdk拆两份
        String prefix = request.getCdk().substring(0, 9);
        CdkCodeModel cdkCodeModel = cdkCodeMapper.selectByFullCode(prefix);
        //使用时间验证
        LogUtils.info("prefix->", prefix, ", cdkCodeModel->", cdkCodeModel);
        if(cdkCodeModel == null){
            return new ErrorResponseDto(ReturnMessage.CDK_NOT_FIND_OR_EXPIRED);
        }
        if(cdkCodeModel.getStartTime().getTime() > System.currentTimeMillis()){
            return new ErrorResponseDto(ReturnMessage.CDK_NOT_OPEN);
        }
        //使用区服验证
        String[] services = cdkCodeModel.getServers().split(";");
        boolean flag = false;
        //0表示所有的区服
        for(String server:services){

            if(flag = (server.equals("0") ||
                server.equals(String.valueOf(request.getServerId())))){
                break;
            }
        }
        if (!flag){
            return new ErrorResponseDto(ReturnMessage.CDK_SERVER_NOT_CONFORM);
        }
        if (request.getServerRuleId() == null
                || (cdkCodeModel.getPlatform() != 10 && CoreUtils.isTrueRule(request.getServerRuleId(),cdkCodeModel.getPlatform()))){
            return new ErrorResponseDto(ReturnMessage.CDK_PLATFORM_ERROR);
        }

        //验证账号创建时间
        if(cdkCodeModel.getCreateRoleTime() != null
                && cdkCodeModel.getCreateRoleTime().getTime() > request.getCreateRoleTime()){
            return new ErrorResponseDto(ReturnMessage.CDK_ROLE_CREATETIME_LATE);
        }
        //验证账号等级
        if(cdkCodeModel.getLevel() > request.getLevel()){
            return new ErrorResponseDto(ReturnMessage.CDK_ROLE_LEVEL_LOW);
        }
        //验证cdk是否存在或者被使用
        String suffix = request.getCdk().substring(9);
        CdkDetailModel detailModel = cdkDetailMapper.findByCode(suffix);
        LogUtils.info("suffix->", suffix, ", detailModel->", detailModel);
        if(detailModel == null ){
            return new ErrorResponseDto(ReturnMessage.CDK_NOT_FIND_OR_EXPIRED);
        }
        //如果是一人一码
        if(cdkCodeModel.getType() == E_CdkCodeType.GROUP_ONCE_USE.getCode()){
            if (detailModel.getIsUse() == 1){
                return new ErrorResponseDto(ReturnMessage.CDK_ALREADY_USE);
            }
        }else{
            //一码多用
            if(cdkCodeModel.getSuccessTotal() >= cdkCodeModel.getTotal()){
                return new ErrorResponseDto(ReturnMessage.CDK_ALREADY_USE);
            }
        }

        /**
         * 当前用户当前cdk的使用情况
         */
        Integer count;
        count = cdkUseRecordMapper.getPlayerUseCountByCdkId(cdkCodeModel.getId(),request.getObjectIndex());
        count = count == null? 0 : count.intValue();
        if(count > 0 && (cdkCodeModel.getType() == E_CdkCodeType.GROUP_ONCE_USE.getCode()
                    || cdkCodeModel.getType() == E_CdkCodeType.SINGLE_REPEAT_USE.getCode()))
            return new ErrorResponseDto(ReturnMessage.CDK_USE_MAX_COUNT);

//        if(cdkCodeModel.getType() == E_CdkCodeType.GROUP_ONCE_USE.getCode()){
//            //当前用户在该组内的激活数量
//            count = cdkUseRecordMapper.getPlayerUseCountInGroup(cdkCodeModel.getChannel() + cdkCodeModel.getProject(), cdkCodeModel.getGroup(), request.getObjectIndex());
//            count = count == null? 0 : count.intValue();
//            if(count >= cdkCodeModel.getTimes()){
//                return new ErrorResponseDto(ReturnMessage.CDK_USE_MAX_COUNT);
//            }
//        }

        cdkUseRecordMapper.insert(new CdkUseRecordModel(cdkCodeModel.getId(),detailModel.getId(), request.getServerId(), request.getObjectIndex(), request.getNickName()));
        cdkDetailMapper.useCdk(detailModel.getId());
        cdkCodeMapper.addSuccessCount(cdkCodeModel.getId());
        return new SuccessResponseDto(cdkCodeModel.getReward());
    }

    @Override
    public BaseResponseDto findServerList(Integer areaId, String gmVersion)
    {
        List<ServerModel> list = serverMapper.findList(areaId==null?0:areaId.intValue(), gmVersion);
        LogUtils.debug("server list -> " + list);
        return new SuccessResponseDto(list);
    }

//    @Override
//    public BaseResponseDto serverListByActivity(String type, Integer id)
//    {
//        if(ConstantFactory.ACTIVITY_CAMP.equals(type))
//            return new SuccessResponseDto(serverMapper.getCampActivityServerList(id));
//        else
//            return null;
//    }




    @Override
    public BaseResponseDto updateVersion(Integer serverId, String version, String password)
    {
        if(serverId == null)
        {
            LogUtils.error("服务器ID错误");
            return new BaseResponseDto(ReturnMessage.PARAM_ERROR);
        }
        //验证密码
        String md5Code = CoreUtils.MD5Encode(String.valueOf(serverId));
        if(!md5Code.equals(password)){
            LogUtils.error("changeStatus 密码错误, 正确密码：" + md5Code);
            LogUtils.debug("update version fail ......... version : " + version );
            return new ErrorResponseDto(ReturnMessage.PASSWORD_ERROR);
        }

        LogUtils.info("update version success ...... version : " + version);
        serverMapper.updateVersion(serverId, version);
        return new SuccessResponseDto();
    }

    @Override
    public BaseResponseDto getServerInfo(Integer id) {
        if(id == null)
        {
            LogUtils.error("服务器ID错误");
            return new BaseResponseDto(ReturnMessage.PARAM_ERROR);
        }
        ServerModel serverModel = serverMapper.selectByPrimaryKey(id);
        if(serverModel == null)
        {
            LogUtils.error("服务器不存在 + " + id);
            return new BaseResponseDto(ReturnMessage.PARAM_ERROR);
        }

        return new SuccessResponseDto(serverModel);
    }

    @Override
    public BaseResponseDto getServerTask(Integer serverId)
    {
        List<ServerTaskModel> list = serverTaskMapper.findByServerId(serverId);
        return new SuccessResponseDto(list);
    }

    /**
     * 获取总的重置数据
     * @param request
     * @return
     */
    @Override
    public BaseResponseDto getTotalRechargeCount(QueryTotalRechargeReqDto request) {
        LogUtils.info("getTotalRechargeCount" + request.toString());
        try {
            List<QueryRechargeCount> list = new ArrayList<>();
            if (System.currentTimeMillis() > request.getStartTime().getTime() && System.currentTimeMillis() < request.getEndTime().getTime()) {
                list.add(new QueryRechargeCount(E_QueryRechargeCountType.DEFINE.getCode(), orderRecordMapper.getTotalRechargeCount(request.getObjectIndex(),
                        request.getStartTimeString(), request.getEndTimeString())));
            }
            TwoTuple<Long, Long> time = CoreUtils.getInDayTime();
            list.add(new QueryRechargeCount(E_QueryRechargeCountType.DAILY.getCode(), orderRecordMapper.getTotalRechargeCount(request.getObjectIndex(),
                    TimeUtils.getFormatTime(time.getFirst()), TimeUtils.getFormatTime(time.getSecond()))));
            time = CoreUtils.getInWeekTime();
            list.add(new QueryRechargeCount(E_QueryRechargeCountType.WEEKLY.getCode(), orderRecordMapper.getTotalRechargeCount(request.getObjectIndex(),
                    TimeUtils.getFormatTime(time.getFirst()), TimeUtils.getFormatTime(time.getSecond()))));
            return new SuccessResponseDto(new CommonResponseListDto<QueryRechargeCount>(list));
        }catch (Exception e){
            LogUtils.errorException(e);
        }
        return new ErrorResponseDto(ReturnMessage.FAILURE);
    }

    @Override
    public BaseResponseDto notifyActivityServerMainServerStart(Integer serverId)
    {
        String host = serverMapper.getCampActivityHttpHostByServerId(serverId);
        if(CoreUtils.isNullOrEmpty(host))
        {
            LogUtils.error("根据主服ID获取活动服HOST错误 -> serverId:" + serverId);
            return new BaseResponseDto(ReturnMessage.PARAM_ERROR);
        }

        ServerModel serverModel = serverMapper.selectByPrimaryKey(serverId);
        if(serverModel != null)
        {
            String url = host + "/camp/serverStart?id={0}&host={1}&port={2}&password={3}";
            String checkString = serverId + "" + TimeUtils.getCurrentTime(TimeUtils.YYYYMMDD);
            url = MessageFormat.format(url, serverId+"", serverModel.getIp(), serverModel.getPort()+"", MD5Utils.encodeUppercase(checkString));
            JSONObject result = HttpJsonUtils.httpPost(url);
            if(result == null)
                return new ErrorResponseDto(ReturnMessage.PARAM_ERROR);

            if(!result.getString("code").equals(ReturnMessage.SUCCESS.getCode()))
            {
                LogUtils.error("通知活动服务器错误 -> " + result.getString("message"));
                return new ErrorResponseDto(ReturnMessage.PARAM_ERROR);
            }
            return new SuccessResponseDto();
        }

        return new BaseResponseDto(ReturnMessage.PARAM_ERROR);
    }

    @Override
    public BaseResponseDto notifyActivityServerModifyServerModel(Integer serverId)
    {
        String host = serverMapper.getCampActivityHttpHostByServerId(serverId);
        if(CoreUtils.isNullOrEmpty(host))
        {
            LogUtils.error("根据主服ID获取活动服HOST错误 -> serverId:" + serverId);
            return new BaseResponseDto(ReturnMessage.PARAM_ERROR);
        }

        HttpJsonUtils.httpPost(host + "/server/modifyServerInfo?id=" + serverId);

        return new SuccessResponseDto();
    }

    @Override
    public BaseResponseDto notifyActivityServerUpdateConfig(Integer id, String path, String version, String password)
    {
        //验证密码
        String md5Code = CoreUtils.MD5Encode(id+""+version);//固定密码
        if(!md5Code.equals(password))
        {
            LogUtils.error("changeStatus 密码错误, 正确密码：" + md5Code);
            LogUtils.debug("update version fail ......... version : " + version );
            return new ErrorResponseDto(ReturnMessage.PASSWORD_ERROR);
        }

        LogUtils.info("notifyActivityServerUpdateConfig ...... id:" + id + " version : " + version + " path:" + path);

        //TODO 活动服接收更新配置文件的接口
        String host = serverMapper.getCampActivityHttpHostById(id);
        if(CoreUtils.isNullOrEmpty(host)) {
            LogUtils.error("根据ID获取活动服HOST错 -> id:" + id);
            return new BaseResponseDto(ReturnMessage.PARAM_ERROR);
        }
        String url = host + "/camp/updateConfig?path={0}&version={1}&password={2}";
        String checkString = id + "" + version + TimeUtils.getCurrentTime(TimeUtils.YYYYMMDD);
        url = MessageFormat.format(url, path, version, MD5Utils.encodeUppercase(checkString));
        HttpJsonUtils.httpPost(url);

        return new SuccessResponseDto();
    }

    @Override
    public BaseResponseDto getCampActivityServerList()
    {
        List<Map<String, Object>> result = serverMapper.getCampActivityServerList();
        for(Map<String, Object> data : result)
        {
            data.remove("info");
        }
        return new SuccessResponseDto(result);
    }

    @Override
    public BaseResponseDto mergeReady(MergeModel mergeModel) {
        if(mergeModel == null)
            return new ErrorResponseDto("合服对象为空");
        if (StringUtil.isNullOrEmpty(mergeModel.getTarget()))
            return new ErrorResponseDto("目标id为空");

        if (StringUtil.isNullOrEmpty(mergeModel.getMerge()))
            return new ErrorResponseDto("合服id为空");
        List<String> mergeList = new ArrayList<>();
        String[] mergerServers = mergeModel.getMerge().split(",");
        Arrays.stream(mergerServers).forEach((str)->mergeList.add(str));
        roleRecordMapper.mergeReady(mergeModel.getTarget(),mergeList);
        //合服之后把被合区的服务器的status设置成5 表示隐藏
        mergeList.forEach((merge)->serverMapper.changeStatus(5,Integer.valueOf(merge)));
        ServerMergeModel serverMergeModel = new ServerMergeModel();
        serverMergeModel.setNewServerId(Integer.valueOf(mergeModel.getTarget()));
        serverMergeModel.setMergeServerIds(mergeModel.getMerge());
        serverMergeModel.setCreateTime(new Date());
        serverMergeMapper.insertMerge(serverMergeModel);
        return new SuccessResponseDto();
    }

    @Override
    public BaseResponseDto getAll() {
        List<Integer> serverList = serverMapper.getAll();
        AuthResult result = new AuthResult();
        if (serverList == null)
            serverList = new ArrayList<>();
        result.setServerList(serverList);
        String datasource = SpringContext.getProperty("spring.datasource.url");
        if (!Utils.isNullOrEmpty(datasource)){
            String[] arr = datasource.split("\\?");
            if (arr != null && arr.length != 0){
                String[] brr = arr[0].split("/");
                if (brr != null && brr.length > 1){
                    result.setAuth(brr[brr.length - 1]);
                    String[] c = brr[brr.length - 2].split(":");
                    if (c != null && c.length > 1){
                        result.setIp(c[0]);
                        result.setPort(c[1]);
                    }else{
                        LogUtils.error("获取ip和端口错误 ->" + brr[brr.length - 2]);
                    }
                }else {
                    LogUtils.error("获取auth失败 brr is null arr[0] ->" + arr[0]);
                }
            }else{
                LogUtils.error("获取auth失败 arr is null datasource ->" + datasource);
            }
        }else{
            LogUtils.error("获取auth失败 ,请检查配置文件");
        }
        String userName = SpringContext.getProperty("spring.datasource.username");
        if (!Utils.isNullOrEmpty(userName))
            result.setUserName(userName);
        String password = SpringContext.getProperty("spring.datasource.password");
        if (!Utils.isNullOrEmpty(password))
            result.setPassword(password);
        return new SuccessResponseDto(JSONObject.toJSONString(result));
    }

    class AuthResult{
        private List<Integer> serverList;
        private String auth;
        private String ip;
        private String port;
        private String userName;
        private String password;

        public List<Integer> getServerList() {
            return serverList;
        }

        public void setServerList(List<Integer> serverList) {
            this.serverList = serverList;
        }

        public String getAuth() {
            return auth;
        }

        public void setAuth(String auth) {
            this.auth = auth;
        }

        public String getIp() {
            return ip;
        }

        public void setIp(String ip) {
            this.ip = ip;
        }

        public String getPort() {
            return port;
        }

        public void setPort(String port) {
            this.port = port;
        }

        public String getUserName() {
            return userName;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }
    }
}
